{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "29e5c911-fa2d-4593-8565-3b7bb127b53d",
   "metadata": {},
   "source": [
    "# LangChain 核心模块 Agent - Self ask with search\n",
    "\n",
    "- Google 搜索对接\n",
    "    - 第三方平台：https://serpapi.com\n",
    "    - LangChain API 封装：`SerpAPIWrapper`\n",
    "- LangChain Agent 模块使用\n",
    "    - Agent 类型：`SELF_ASK_WITH_SEARCH`\n",
    "    - Agent 实例化：`initialize_agent` 方法\n",
    " \n",
    "LangChain 内置 Agent类型详见：https://python.langchain.com/docs/modules/agents/agent_types/"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "8a484703-b880-4cb5-b5f5-d917cfd72451",
   "metadata": {},
   "outputs": [],
   "source": [
    "%%capture --no-stderr\n",
    "%pip install -U langchain"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6d25fb22-f953-40e7-9902-24f58a623620",
   "metadata": {},
   "source": [
    "以下`SERPAPI_API_KEY`仅为示例，请访问 https://serpapi.com 注册账号并替换为自己的 `API_KEY`（每月100次免费调用）\n",
    "\n",
    "```python\n",
    "import os\n",
    "\n",
    "# 更换为自己的 Serp API KEY\n",
    "os.environ[\"SERPAPI_API_KEY\"] = \"xxx\"\n",
    "```\n",
    "\n",
    "建议将其设置为环境变量，而不是在代码中显式明文设置"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "add0b59e-9e30-41a1-9a4e-bacf8aefb3e9",
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain_openai import OpenAI\n",
    "from langchain.utilities import SerpAPIWrapper\n",
    "from langchain.agents import initialize_agent, AgentType, Tool\n",
    "\n",
    "llm = OpenAI(model_name=\"gpt-3.5-turbo-instruct\", temperature=0)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "7047f1b0-a29c-497e-badc-d02fbcbf4082",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 实例化查询工具\n",
    "search = SerpAPIWrapper()\n",
    "tools = [\n",
    "    Tool(\n",
    "        name=\"Intermediate Answer\",\n",
    "        func=search.run,\n",
    "        description=\"useful for when you need to ask with search\",\n",
    "    )\n",
    "]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "08a5daa3-fc7a-4ce9-aa46-ad4a6d31be74",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/tmp/ipykernel_1746044/2069300735.py:2: LangChainDeprecationWarning: The function `initialize_agent` was deprecated in LangChain 0.1.0 and will be removed in 1.0. Use Use new agent constructor methods like create_react_agent, create_json_agent, create_structured_chat_agent, etc. instead.\n",
      "  self_ask_with_search = initialize_agent(\n"
     ]
    }
   ],
   "source": [
    "# 实例化 SELF_ASK_WITH_SEARCH Agent\n",
    "self_ask_with_search = initialize_agent(\n",
    "    tools, llm, agent=AgentType.SELF_ASK_WITH_SEARCH, verbose=True\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "508c39d7-05d9-4486-83bc-924cd6a1c499",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n",
      "\u001b[32;1m\u001b[1;3m Yes.\n",
      "Follow up: 第几届大运会是在哪一年举办的？\u001b[0m\n",
      "Intermediate answer: \u001b[36;1m\u001b[1;3m大运会所有必选竞赛项目全部是奥运项目，竞赛管理由国际单项体育组织按照奥运标准实施，是规模仅次于奥运会的世界综合性运动会，素有“小奥运会”之称。 2023年7月28日至8月8日，第31届世界大学生夏季运动会在四川成都举办。\u001b[0m\n",
      "\u001b[32;1m\u001b[1;3mFollow up: 2023年大运会的举办地是哪个城市？\u001b[0m\n",
      "Intermediate answer: \u001b[36;1m\u001b[1;3m成都第31届世界大学生夏季运动会，将于7月28日开幕。 第31届世界大学生夏季运动会将于7月28日至8月8日在四川成都举行。 在龙泉驿区的东安湖畔，形如“银色飞碟”的东安湖体育公园主体育场，是大运会开幕式主场馆，成为蓉城又一地标。\u001b[0m\n",
      "\u001b[32;1m\u001b[1;3mSo the final answer is: 第31届大运会，2023年，成都\u001b[0m\n",
      "\n",
      "\u001b[1m> Finished chain.\u001b[0m\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "{'input': '成都举办的大运会是第几届大运会？2023年大运会举办地在哪里？', 'output': '第31届大运会，2023年，成都'}"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 实际运行 Agent，查询问题（正确）\n",
    "self_ask_with_search.invoke(\n",
    "    \"成都举办的大运会是第几届大运会？2023年大运会举办地在哪里？\"\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "5fe1f2de-f982-4953-9e8e-7f99a8289975",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n",
      "\u001b[32;1m\u001b[1;3m Yes.\n",
      "Follow up: 2023年大运会是第几届大运会？\u001b[0m\n",
      "Intermediate answer: \u001b[36;1m\u001b[1;3m2023成都第31届世界大学生运动会开幕式& 2023 The 31 FISU World University Games - Opening Ceremony(4K HDR) - YouTube.\u001b[0m\n",
      "\u001b[32;1m\u001b[1;3mFollow up: 成都是第几届大运会举办地？\u001b[0m\n",
      "Intermediate answer: \u001b[36;1m\u001b[1;3m2021年夏季世界大学生运动会（英语：2021 Summer World University Games）简称为2021年成都大运会或成都大运会，是第31届夏季世界大学生运动会，原定于2021年于中国四川省成都市举行，后因2019冠状病毒病疫情等原因二次延期，最终改至2023年7月28日至8月8日举行。\u001b[0m\n",
      "\u001b[32;1m\u001b[1;3mSo the final answer is: 成都\u001b[0m\n",
      "\n",
      "\u001b[1m> Finished chain.\u001b[0m\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "{'input': '2023年大运会举办地在哪里？成都举办的大运会是第几届大运会？', 'output': '成都'}"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 实际运行 Agent，查询问题\n",
    "self_ask_with_search.invoke(\n",
    "    \"2023年大运会举办地在哪里？成都举办的大运会是第几届大运会？\"\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "e1cf918e-a58a-4790-a4c4-2109f23dd064",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "成都举办的大运会是第31届大运会。\n"
     ]
    }
   ],
   "source": [
    "# Reason-only 正确：启发式 Prompt（猜测是大运会新闻报道数据给到了 gpt-3.5-turbo-instruct 模型）\n",
    "print(llm.invoke(\"成都举办的大运会是第几届大运会？\"))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "32021fdf-2597-4dde-a425-13650904671f",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "2023年大运会的举办地将在中国的重庆市。\n"
     ]
    }
   ],
   "source": [
    "# Reason-only 错误：非启发式 Prompt（容易出现事实类错误，未结合 Web Search 工具）\n",
    "print(llm.invoke(\"2023年大运会举办地在哪里？\"))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b73c7bd9-a835-41c1-bf28-4e203c22538b",
   "metadata": {},
   "source": [
    "#### 使用 GPT-4 作为大语言模型实现更优的 ReAct 范式"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "d98ba940-a6e8-477e-83a9-2e20115ff51d",
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain_openai import ChatOpenAI\n",
    "\n",
    "chat_model = ChatOpenAI(model=\"gpt-4o-mini\", temperature=0)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "fc4347f2-4a16-4406-92c7-d2156478bb56",
   "metadata": {},
   "outputs": [],
   "source": [
    "self_ask_with_search_chat = initialize_agent(\n",
    "    tools, chat_model, agent=AgentType.SELF_ASK_WITH_SEARCH, verbose=True\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "25978771-8e69-41f2-b9e8-b287d846e1cd",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n",
      "\u001b[32;1m\u001b[1;3mYes.  \n",
      "Follow up: 成都举办的大运会是第几届大运会？  \u001b[0m\n",
      "Intermediate answer: \u001b[36;1m\u001b[1;3m2021年夏季世界大学生运动会（英语：2021 Summer World University Games）简称为2021年成都大运会或成都大运会，是第31届夏季世界大学生运动会，原定于2021年于中国四川省成都市举行，后因2019冠状病毒病疫情等原因二次延期，最终改至2023年7月28日至8月8日举行。\u001b[0m\n",
      "\u001b[32;1m\u001b[1;3mSo the final answer is: 第31届大运会，举办地是成都。\u001b[0m\n",
      "\n",
      "\u001b[1m> Finished chain.\u001b[0m\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "{'input': '成都举办的大运会是第几届大运会？2023年大运会举办地在哪里？', 'output': '第31届大运会，举办地是成都。'}"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# GPT-4 based ReAct 答案（正确）\n",
    "self_ask_with_search_chat.invoke(\n",
    "     \"成都举办的大运会是第几届大运会？2023年大运会举办地在哪里？\"\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "94da622a-8bdd-4cf3-bc7a-bcfbf88c54f4",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.14"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
